function helloWorld(){
    console.log('helloWorld')
}
helloWorld()

// 基本类型
// boolean类型
let tru:Boolean = false
console.log(tru)
// 数字类型
let count:Number = 20
console.log(count)
// 字符串类型
let str:String = 'yhx'
console.log(str)
// Symbol类型
const sym = Symbol()
let obj = {
    [sym]:'Semlinker'
}
console.log(obj[sym])
// Array类型
let list:String[] = ['1','2','3']
let list2:Array<number> = [1,2,3]  //Array<number>泛型语法
// Enum类型  枚举可以定义一些带数字的常量
// 数字枚举   不赋值时默认从0开始 赋值后默认增加
enum Direction {
    a = 3,
    b,
    c,
    d
}
let dir:Direction = Direction.a
console.log(dir)
console.log(Direction.b)
// 字符串枚举
enum Strection {
    a = '1',
    b = '2',
    c = '3'
}
let str2:Strection = Strection.a
console.log(str2)
// 常量枚举
const enum Contion {
    a,
    b,
}
const con:Contion = Contion.a
console.log(con)
// 异构枚举  成员值是数字和字符串的结合
enum Enum {
    A,
    B,
    C = 'C',
    D = 8,
    E
}
console.log(Enum.A) // 0
console.log(Enum[0]) //A  //数字枚举相对字符串枚举多了 “反向映射”：

// any类型 任何类型都可以为any类型
let notSure:any = '222'
notSure = 1,
notSure = false
notSure = ['1','2']
console.log(notSure)

// 元组类型  单个变量中存储不同类型的值
let tupleType:[String,Boolean] = ['111',false]
console.log(tupleType[1])

// void类型与any类型相反当一个函数没有返回值时，通常会见到返回值为void
function WarnUser():void{
    console.log('你错拉吗')
}
WarnUser()
// null 和 undefined
let u:undefined = undefined
let n:null = null

// 对象类型
let obj1 = {
    name:'yxh'
}
console.log(obj1)

// never类型 永不存在的值



// 类型断言（两种形式）
// 1.<>尖括号用法
// let someVale:any = "this is a String"
// let strLength:number = (<string>someVale).length
// console.log(someVale,strLength)
// 2.as用法
let someVale:any = "this is a String"
let strLength:number = ( someVale as string).length
console.log(someVale,strLength)

// 确定赋值断言
let x!:number
addx()
console.log(2 + x)
function addx(){
    x = 10
}

// 类型守卫
// interface Admin {
//     name: string;
//     privileges: string[];
// }
// interface Employee {
//     name: string,
//     is: boolean
// }
// type UnknownEmployee = Employee | Admin;
// let abc:UnknownEmployee = {
//     name:'yhx',
//     is: false,
//     privileges:['1','2']
// }
// console.log(abc)

// function printEmployeeInformation(emp: UnknownEmployee) {
//     console.log("Name: " + emp.name);
//     if ("privileges" in emp) {
//       console.log("Privileges: " + emp.privileges);
//     }
//     if ("is" in emp) {
//       console.log("is: " + emp.is);
//     }
// }
// printEmployeeInformation(abc)

// 可辨识联合类型
interface Motorcycle {
    vType: "motorcycle"; // discriminant
    make: number; // year
}

interface Car {
    vType: "car"; // discriminant
    age: number
}

interface Truck {
    vType: "truck"; // discriminant
    capacity: number; // in tons
}
type Vehicle = Motorcycle | Car | Truck;
const EVALUATION_FACTOR = Math.PI; 
function evaluatePrice(vehicle: Vehicle) {
    switch(vehicle.vType) {
      case "car":
        return vehicle.age * EVALUATION_FACTOR;
      case "truck":
        return vehicle.capacity * EVALUATION_FACTOR;
      case "motorcycle":
        return vehicle.make * EVALUATION_FACTOR;
    }
}
console.log( EVALUATION_FACTOR)

const myTruck: Truck = { vType: "truck", capacity: 12 };
console.log( evaluatePrice(myTruck) )
console.log( evaluatePrice({ vType: 'car', age:12}) )
// 


// 类型别名 起个新名字
type Message = string | string[]
let greet = (message:Message) =>{}

// 交叉类型
type Part = { x:number }
type Point = Part & {y:number}
let po:Point = {
    x:1,
    y:2,
}
console.log(po)
// 同名基础类型的合并
// interface X {
//     c: string;
//     d: string;
// }
  
// interface Y {
//     c: number;
//     e: string
// }

// type XY = X & Y;
// type YX = Y & X;

// let p: XY = {
//     c:1,
//     d:'1',
//     e:'1'
// };

// 同名非基础类型合并会成功
interface D { d: boolean; }
interface E { e: string; }
interface F { f: number; }

interface A { x: D; }
interface B { x: E; }
interface C { x: F; }

type ABC = A & B & C;

let abc: ABC = {
  x: {
    d: true,
    e: 'semlinker',
    f: 666
  }
};

console.log('abc:', abc);

// typeScript函数

// 箭头函数
// var publishDate:number
function Book() {
    // console.log(this)
    // this.publishDate = 2016;
    // setInterval(() => {
    //   console.log(this.publishDate);
    // }, 1000);
}
Book()

// let IdGenerator: (chars: string, nums: number) => string;
// function create(name:string,id:number):string{
//     return name + id
// }
// IdGenerator = create;
// console.log( create('yhx',20) )
// console.log( IdGenerator )

// 可选参数和默认参数
function create(name:string,id:number,age?:number):string{
    return name + id
}
function create2(name:string = 'yhx',id:number,age?:number):string{
    return name + id
}

// 剩余参数
function push(qwe:any, ...items:number[]) {
  items.forEach(function (item:number) {
    qwe.push(item);
  });
}

let arr:any = [];
push(arr, 1, 2, 3);
console.log(arr,'剩余参数')






// 接口 
// 可读和只读属性
interface Person {
    readonly name: string,
    age?:Number
}
let p1:Person = {
    name:'yhx',
}
console.log(p1)

let a: number[] = [1, 2, 3, 4];
let ro: ReadonlyArray<number> = a;
console.log(a[0],ro)


// 3.任意属性
interface Person2 {
    name: string;
    age?: number;
    [propName: string]: any;
}
const p2:Person2 = { name: "semlinker" };
const p3:Person2 = { name: "lolo", age: 5 };
const p4:Person2 = { name: "kakuqo", sex: 1 }
console.log(p2,p3,p4)

// 4.接口和类型别名的区别
type Point2 = {
    x: number;
    y: number;
};
type SetPoint = (x: number, y: number) => void;
console.log()


// interface PartialPointX { x: number; }
// type Point = PartialPointX & { y: number; };
// 5.Implements
interface o {
    x:number,
    y:number
}
class o1 implements o{
    x=1;
    y=1
}

// 报错
// type PartialPoint = { x: number; } | { y: number; };
// class o12 implements PartialPoint{
//     x=1;
//     y=1
// }


// 类的私有属性

// class Child {
//     #name:string;
//     constructor(name:string){
//         this.#name = name
//     }
//     greet(){
//         console.log( `heelo,my name is ${this.#name}`)
//     }
// }
// let chi = new Child('王燕南')
// chi.greet()
// chi.#name

// let passcode = "Hello TypeScript";
// class Animal {
//     constructor(name:string) {
//       this.name = name;
//     }
//     get name() {
//       return 'Jack';
//     }
//     set name(value) {
//       console.log('setter: ' + value);
//     }
//   }
// let a2 = new Animal('Kitty'); // setter: Kitty
// a2.name = 'Tom'; // setter: Tom
// console.log(a2.name); // Jack

// // 类的继承
// class Animla {
//     name:string;
//     constructor(name:string){
//         this.name = name
//     }
//     sayHi(){
//         return `my name is ${this.name}`
//     }
// }
// let an = new Animla('熊猫')
// console.log( an.sayHi())
// class Cart extends Animla {
//     constructor(name:string){   
//         super(name);        //调用父类的constructor
//         console.log(this.name)
//     }
//     sayHi(): string {
//         return '继承' + super.sayHi() //调用父类的sayHi
//     }
// }
// let c = new Cart('猫咪')
// console.log(c.sayHi())

// 类的修饰符
class Child {
    #name:string;
    public constructor(name:string){
        this.#name = name
    }
    protected greet(){
        console.log( `heelo,my name is ${this.#name}`)
    }
}
let chi = new Child('王燕南')
// chi.greet() //报错 prot修饰的只有在子类中可以访问
class Yhx extends Child {
    send(){
        super.greet()
    }
}
let yh = new Yhx('hhaha')
yh.send()//heelo,my name is hhaha


// 类实现接口
interface Alarm{
    alert():void
}
interface Light {
    lightOn():void;
    lightOff():void;
}
class Cartt implements Alarm,Light {
    alert() {
        console.log('Cartt alert')
    }
    lightOn() {
        console.log('Cartt light on');
    }
    lightOff() {
        console.log('Cartt light off');
    }
}
let carr = new Cartt()
carr.alert()
carr.lightOn()
// console.log(carr)

// type aaa = {
//     x:number
// }

// let a3:aaa = {
//     x:1
// }
// console.log(a3)


// 泛型 在定义函数、接口、类的时候，不预先指定具体的类型，而在使用的时候再指定类型的一种特性
// Array<any>  数组泛型
// function creatApp(length:number,value:any):Array<any>{
//     let result = []
//     for(let i = 0;i<length; i++){
//         result[i] = value
//     }
//     return result
// }
// let res = creatApp(2,2)
// console.log( res )

// T用来指任意类型 在调用的时候指定他的类型  也可以不指定默认推算出来
function creatApp<T>(length:number,value:T):Array<T>{
    let result:T[] = []
    for(let i = 0;i<length; i++){
        result[i] = value
    }
    return result
}
let res = creatApp<string>(2,'1')
console.log( res )



// 定义多个类型参数
function createVue<T,U>(value:T,message:U):T{
    console.log(message)
    return value
}
console.log(createVue<string,number>('yhx',1) )
console.log(createVue('yhx',1) )

// 泛型接口
interface Identities<V,U> {
    val:V,
    meg:U
}
function createFan<V,U>(val:V,meg:U) :Identities<V,U> {
    console.log(val+":" + typeof (val) )  //   1:number 
    console.log( meg+":"+ typeof(meg) )   //   2:number
    let idens:Identities<V,U> = {
        val,
        meg
    }
    return idens
}
console.log( createFan(1,2)) // {val: 1, meg: 2}

